package com.example.service.impl;

import com.alibaba.fastjson.JSON;
import com.example.Req.LotteryTicketReq;
import com.example.common.BizException;
import com.example.common.Pagination;
import com.example.mapper.LotteryTicketMapper;
import com.example.model.FcapNoContent;
import com.example.model.LotteryTicket;
import com.example.model.LotteryTicketRes;
import com.example.model.NumberRes;
import com.example.model.TicketContent;
import com.example.service.LotteryTicketService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

@Service
@Slf4j
public class LotteryTicketServiceImpl implements LotteryTicketService {
    private static Set<String> colorSet = new HashSet<String>() {{
        add("blue");
        add("red");
        add("green");
    }};

    private static Set<String> wuxingSet = new HashSet<String>() {{
        add("金");
        add("木");
        add("水");
        add("火");
        add("土");
    }};

    private static Set<String> animalSet = new HashSet<String>() {{
        add("鼠");
        add("牛");
        add("虎");
        add("兔");
        add("龙");
        add("蛇");
        add("马");
        add("羊");
        add("猴");
        add("鸡");
        add("狗");
        add("猪");
    }};
    @Autowired
    private LotteryTicketMapper lotteryTicketMapper;
    private final String SEPARTOR = ",";
    @Autowired
    private ExecutorService workStealingService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchInsertLotteryTicket(int year, int type) {
        try {
            String url = "https://kjh.55128.cn/hk6-history-";
            if(type == 2){
                url = "https://kjh.55128.cn/am6hc-history-";
            }
            //URL url = new URL("https://kjh.55128.cn/hk6-history-2022.htm");
            //Document document = Jsoup.parse(url, 100000);
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> result = restTemplate.getForEntity(url + year + ".htm", String.class);
            String str = result.getBody();
            Document document = Jsoup.parse(str);

            Elements element = document.getElementsByTag("body");
            Elements mainElements = element.first().getElementsByClass("main");
            //log.info(mainElements.html());

            Elements div = mainElements.first().getElementsByClass("detail-wrapper");
            Element divTable = document.getElementById("table");
            Element table = divTable.getElementsByTag("table").first();
            // 解析thead标签以及下面的th ,去掉多余的th 标签
            Element theadTr = table.getElementsByTag("thead").first()
                    .getElementsByTag("tr").first();
            Elements theadTrTh = theadTr.getElementsByTag("th");
            theadTrTh.remove(7);
            theadTrTh.remove(6);
            theadTrTh.remove(5);
            theadTrTh.remove(4);
            theadTrTh.remove(3);
            theadTr.empty();
            for (Element th : theadTrTh) {
                theadTr.append(th.toString());
            }
            log.info(theadTr.html());

            Element tbodyElement = table.getElementsByTag("tbody").first();

            // 解析 tbody 标签 以及下面的
            Elements tBodyTrList = table.getElementsByTag("tbody").first()
                    .getElementsByTag("tr");
            List<LotteryTicket> lotteryTickets = new ArrayList<>();
            for (Element tBodyTr : tBodyTrList) {
                Elements tBodyTrTdList = tBodyTr.getElementsByTag("td");
                tBodyTrTdList.remove(8);
                tBodyTrTdList.remove(7);
                tBodyTrTdList.remove(6);
                tBodyTrTdList.remove(5);
                tBodyTrTdList.remove(4);
                tBodyTrTdList.remove(3);
                tBodyTr.empty();
                // 遍历td
                for (Element td : tBodyTrTdList) {
                    log.info(td.html().trim());
                    tBodyTr.append(td.toString());
                }
                // 买🐎 对象
                LotteryTicket lotteryTicket = new LotteryTicket();

                Element dateElement = tBodyTrTdList.get(0); // 开奖日期
                lotteryTicket.setPublishDate(dateElement.html().trim());

                Element noElement = tBodyTrTdList.get(1);   // 开奖期数
                lotteryTicket.setNo(noElement.html().trim());

                Element numberModuleElement = tBodyTrTdList.get(2);   // 开奖号码模块
                Elements divElementList = numberModuleElement.getElementsByTag("div");

                Element numberDivElement = divElementList.get(0);  // 号码
                Elements numberDivSpanElements = numberDivElement.getElementsByTag("span");
                List<TicketContent> ticketContents = new ArrayList<>();
                List<String> contentList = new ArrayList<>();
                List<String> colorList = new ArrayList<>();
                for (Element numberDivSpan : numberDivSpanElements) {
                    Set<String> spanClassNames = numberDivSpan.classNames();
                    if (spanClassNames.contains("gray")) {
                        continue;
                    }
                    spanClassNames.retainAll(colorSet);
                    TicketContent ticketContent = new TicketContent();
                    ticketContent.setColor(spanClassNames.iterator().next()); // 颜色
                    ticketContent.setContent(numberDivSpan.html().trim()); //号码

                    contentList.add(ticketContent.getContent());
                    colorList.add(ticketContent.getColor());
                    ticketContents.add(ticketContent);
                }
                log.info("ticketContents:{}", JSON.toJSONString(ticketContents));
                lotteryTicket.setContent(String.join(SEPARTOR, contentList));
                lotteryTicket.setColor(String.join(SEPARTOR, colorList));
                lotteryTicket.setType(type);
                lotteryTicket.setTableIndex(type%2);
                Element animalDivElement = divElementList.get(1);  // 生肖
                List<String> animalList = new ArrayList<>();
                Elements animalDivSpanElements = animalDivElement.getElementsByTag("span");
                for (Element animalDivSpan : animalDivSpanElements) {
                    String a = animalDivSpan.html().trim();
                    if (animalSet.contains(a)) {
                        animalList.add(a);
                    }
                }
                log.info("animalList:{}", JSON.toJSONString(animalList));
                lotteryTicket.setAnimalList(animalList);
                lotteryTicket.setAnimal(String.join(SEPARTOR, animalList));

                Element wuxingDivElement = divElementList.get(2);  // 五行
                Elements wuxingDivSpanElements = wuxingDivElement.getElementsByTag("span");
                List<String> wuxingList = new ArrayList<>();
                for (Element wuxingDivSpan : wuxingDivSpanElements) {
                    String a = wuxingDivSpan.html().trim();
                    if (wuxingSet.contains(wuxingDivSpan.html().trim())) {
                        wuxingList.add(a);
                        ;
                    }
                }
                log.info("wuxingList:{}", JSON.toJSONString(wuxingList));
                lotteryTicket.setWuxingList(wuxingList);
                lotteryTicket.setWuxing(String.join(SEPARTOR, wuxingList));

                lotteryTickets.add(lotteryTicket);
            }
            log.info("tbodyElement:{}", tbodyElement.html());
            log.info("lotteryTicketList:{}", JSON.toJSONString(lotteryTickets));
            if (CollectionUtils.isEmpty(lotteryTickets)) {
                return 0;
            }
            lotteryTickets.sort(new Comparator<LotteryTicket>() {
                @Override
                public int compare(LotteryTicket o1, LotteryTicket o2) {
                    return Integer.parseInt(o1.getNo()) - Integer.parseInt(o2.getNo());
                }
            });
            lotteryTicketMapper.batchInsertLotteryTicket("fcap_lottery_ticket"+type,lotteryTickets);
            lotteryTicketMapper.batchUpdateSerialNo("fcap_lottery_ticket"+type, type);
            log.info("==================================");


        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Transactional
    public void calculateRepeat(String sort, int type) throws Exception {
        List<LotteryTicket> list = lotteryTicketMapper.selectTicketList(sort, type, "fcap_lottery_ticket"+type);
        log.info("start:{}", JSON.toJSONString(list));
        if (list == null && list.size() == 0) {
            throw new BizException("00000001", "没有数据");
        }
        Map<Long, LotteryTicket> map = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            map.put(lotteryTicket.getId(), lotteryTicket);
        }
        LotteryTicket ticket = list.get(0);
        long currentId = ticket.getId();

        LotteryTicket maxTicket = list.get(list.size() - 1);
        long max = maxTicket.getId();

        for (int i = 1; i < 8; i++) {
            if ("desc".equals(sort)) {
                cal(map, currentId, i);
            } else {
                cal2(map, currentId, i, max);
            }
        }
        log.info("list:{}", JSON.toJSONString(list));
        lotteryTicketMapper.batchUpdateLotteryTicket(list, "fcap_lottery_ticket"+type);
    }

    private void cal(Map<Long, LotteryTicket> map, long currentId, int num) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        while (currentId > 0) {
            LotteryTicket current = map.get(currentId);
            String[] currentArr = current.getContent().split(SEPARTOR);
            List<String> currentContentList = new ArrayList<>();
            for (String a : currentArr) {
                currentContentList.add(a);
            }

            LotteryTicket next = map.get(currentId - num);
            if (next == null) {
                break;
            }
            String[] nextArrs = next.getContent().split(SEPARTOR);
            List<String> nextContents = new ArrayList<>();
            for (String aa : nextArrs) {
                nextContents.add(aa);
            }
            log.info("{} - contentList:{}", current.getNo(), JSON.toJSONString(currentContentList));
            log.info("{} - nextContents:{}", next.getNo(), JSON.toJSONString(nextContents));
            currentContentList.retainAll(nextContents);
            log.info("交集:{}", JSON.toJSONString(currentContentList));

            Method m = LotteryTicket.class.getMethod("setS" + num, Integer.class);
            if (CollectionUtils.isEmpty(currentContentList)) {
                m.invoke(current, 0);
            } else {
                m.invoke(current, 1);
            }
            log.info("{} - current:{}", current.getNo(), JSON.toJSONString(current));

            currentId = currentId - 1;
        }
    }

    private void cal2(Map<Long, LotteryTicket> map, long currentId, int num, long max) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        while (currentId <= max) {
            LotteryTicket current = map.get(currentId);
            String[] currentArr = current.getContent().split(SEPARTOR);
            List<String> currentContentList = new ArrayList<>();
            for (String a : currentArr) {
                currentContentList.add(a);
            }

            LotteryTicket next = map.get(currentId + num);
            if (next == null) {
                break;
            }
            String[] nextArrs = next.getContent().split(SEPARTOR);
            List<String> nextContents = new ArrayList<>();
            for (String aa : nextArrs) {
                nextContents.add(aa);
            }
            log.info("{} - contentList:{}", current.getNo(), JSON.toJSONString(currentContentList));
            log.info("{} - nextContents:{}", next.getNo(), JSON.toJSONString(nextContents));
            nextContents.retainAll(currentContentList);
            log.info("交集:{}", JSON.toJSONString(nextContents));

            Method m = LotteryTicket.class.getMethod("setS" + num, Integer.class);
            if (CollectionUtils.isEmpty(nextContents)) {
                m.invoke(next, 0);
            } else {
                m.invoke(next, 1);
            }
            log.info("{} - current:{}", current.getNo(), JSON.toJSONString(next));

            currentId = currentId + 1;
        }
    }


    /*public Pagination<LotteryTicketRes> getRepeatList(LotteryTicketReq req) {
        Pagination<LotteryTicketRes> pagination;
        List<Long> list;
        Long maxSerialNo = lotteryTicketMapper.getMaxSerialNo();
        if (maxSerialNo == null) {
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }
        int total = lotteryTicketMapper.selectNonRepeatTicketListCountNew(maxSerialNo, req.getNumber());
        if (total == 0) {
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }

        pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), total);

        List<LotteryTicketRes> resultList = lotteryTicketMapper.selectNonRepeatTicketListNew(maxSerialNo, req.getNumber(), req);

        if (CollectionUtils.isEmpty(resultList)) {
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }
        pagination.setList(resultList);
        return pagination;
    }*/

        /*Map<Long, Long> repeatRecordMap = new HashMap();

        List<Long> idList = new ArrayList<>();

        for(int i = 0; i < list.size()-1; i++){
            int j = i + 1;
            if(list.get(i)-1 - list.get(j) >= req.getRepeat()){
                repeatRecordMap.put(list.get(i)-1, (list.get(i)- 1 - list.get(j))); // 重复次数
                idList.add(list.get(i)-1);
            }
        }

        if(CollectionUtils.isEmpty(idList)){
            log.info("getRepeatList idList is null");
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }

        // 分页
        int total = idList.size();
        int startIndex = (req.getPageNo() -1) * req.getPageSize();
        List<Long> newIdList = new ArrayList<>();
        for(int i = startIndex; i < startIndex + req.getPageSize(); i++){
            if(i >= idList.size()){
                break;
            }
            newIdList.add(idList.get(i));
        }
        pagination = new Pagination<>(req.getPageNo(), req.getPageSize(), total);
        if(CollectionUtils.isEmpty(newIdList)){
            log.info("getRepeatList newIdList is null");
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }

        List<LotteryTicketRes> resultList = lotteryTicketMapper.selectTicketListById(newIdList);
        if(CollectionUtils.isEmpty(resultList)){
            log.info("getRepeatList resultList is null");
            pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), 0);
            pagination.setList(new ArrayList<>());
            return pagination;
        }*/
    // for(LotteryTicketRes lotteryTicketRes: resultList){
    // 生肖
/*            String[] animal = lotteryTicketRes.getAnimal().split(SEPARTOR);
            List<String> animalList = new ArrayList<>();
            for(String a: animal){
                animalList.add(a);
            }
            animalList.add(6, "");
            // 五行
            String[] wuxing = lotteryTicketRes.getWuxing().split(SEPARTOR);
            List<String> wuxingList = new ArrayList<>();
            for(String b: wuxing){
                wuxingList.add(b);
            }
            wuxingList.add(6, "");
            lotteryTicketRes.setAnimalList(animalList);
            lotteryTicketRes.setWuxingList(wuxingList);*/

    // String[] content = lotteryTicketRes.getContent().split(SEPARTOR);
    //String[] color = lotteryTicketRes.getColor().split(SEPARTOR);

    // 组装颜色和数字
            /*List<TicketContent> contentList = new ArrayList<>();
            for(int i = 0; i < content.length; i++){
                TicketContent ticketContent = new TicketContent();
                ticketContent.setContent(content[i]);
                //ticketContent.setColor(color[i]);
                if(i == 6){
                    ticketContent.setColor("green");
                }else{
                    ticketContent.setColor("red");
                }

                contentList.add(ticketContent);
            }*/
            /*TicketContent temp = new TicketContent();
            temp.setContent("+");
            temp.setColor("gray");
            contentList.add(6, temp);*/

            /*lotteryTicketRes.setContentList(contentList);

            lotteryTicketRes.setRepeat(repeatRecordMap.get(lotteryTicketRes.getId()));
        }

        pagination.setList(resultList);
*/


    public Pagination<LotteryTicketRes> getTicketListPage(LotteryTicketReq req) {
        req.setTableName("fcap_lottery_ticket"+req.getType());
        int count = lotteryTicketMapper.selectTicketsCount(req);
        Pagination<LotteryTicketRes> pagination = new Pagination<LotteryTicketRes>(req.getPageNo(), req.getPageSize(), count);
        if (count <= 0) {
            pagination.setList(new ArrayList<LotteryTicketRes>());
        }
        List<LotteryTicketRes> resultList = lotteryTicketMapper.selectTickets(req);

        for (LotteryTicketRes lotteryTicketRes : resultList) {
            // 生肖
            /*String[] animal = lotteryTicketRes.getAnimal().split(SEPARTOR);
            List<String> animalList = new ArrayList<>();
            for(String a: animal){
                animalList.add(a);
            }
            animalList.add(6, "");*/
            // 五行
            /*String[] wuxing = lotteryTicketRes.getWuxing().split(SEPARTOR);
            List<String> wuxingList = new ArrayList<>();
            for(String b: wuxing){
                wuxingList.add(b);
            }
            wuxingList.add(6, "");
            lotteryTicketRes.setAnimalList(animalList);
            lotteryTicketRes.setWuxingList(wuxingList);
*/
            String[] content = lotteryTicketRes.getContent().split(SEPARTOR);
            //String[] color = lotteryTicketRes.getColor().split(SEPARTOR);

            // 组装颜色和数字
            List<TicketContent> contentList = new ArrayList<>();
            for (int i = 0; i < content.length; i++) {
                TicketContent ticketContent = new TicketContent();
                ticketContent.setContent(content[i]);
                if (i == 6) {
                    ticketContent.setColor("green");
                } else {
                    ticketContent.setColor("red");
                }

                contentList.add(ticketContent);
            }
         /*   TicketContent temp = new TicketContent();
            temp.setContent("+");
            temp.setColor("gray");
            contentList.add(6, temp);*/
            lotteryTicketRes.setContentList(contentList);
        }

        pagination.setList(resultList);

        return pagination;
    }


    @Transactional
    public void calculateNewDataRepeat(String sort, int num) throws Exception {
        List<LotteryTicket> list = lotteryTicketMapper.selectTicketListLimit(sort, num);
        log.info("start:{}", JSON.toJSONString(list));
        if (list == null && list.size() == 0) {
            throw new BizException("00000001", "没有数据");
        }
        Map<Long, LotteryTicket> map = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            map.put(lotteryTicket.getId(), lotteryTicket);
        }
        LotteryTicket ticket = list.get(0);
        long currentId = ticket.getId();

        LotteryTicket maxTicket = list.get(list.size() - 1);
        long max = maxTicket.getId();

        for (int i = 1; i < 8; i++) {
            if ("desc".equals(sort)) {
                cal(map, currentId, i);
            } else {
                cal2(map, currentId, i, max);
            }
        }
        log.info("list:{}", JSON.toJSONString(list));
        lotteryTicketMapper.batchUpdateLotteryTicket(list, "fcap_lottery_ticket");
    }

    public int insertLotteryTicket(LotteryTicketReq req) {
        req.setTableName("fcap_lottery_ticket"+req.getType());
        lotteryTicketMapper.insertLotteryTicket(req);

        NumberRes numberRes = lotteryTicketMapper.getSubtractSerialNo(req.getType(), "fcap_lottery_ticket"+req.getType());
        if (numberRes == null || numberRes.getBig() == null
                || numberRes.getSmall() == null || numberRes.getSubtract() == null) {
            log.error("jiSuanRepeat numberRes is null, return...");
            return 0;
        }
        if (numberRes.getSubtract().longValue() <= 1) {
            log.error("jiSuanRepeat getSubtract is error, return...");
            return 0;
        }
        List<String> repeatList = lotteryTicketMapper.getRepeatSerialNo(req.getType(), "fcap_lottery_ticket"+req.getType());
        if (!CollectionUtils.isEmpty(repeatList)) {
            throw new BizException("00000001", "这些序号出现了重复" + String.join("，", repeatList) + "。请修改序号");
        }
        LotteryTicketReq queryReq = new LotteryTicketReq();
        queryReq.setType(req.getType());
        queryReq.setTableName("fcap_lottery_ticket"+req.getType());
        Integer count = lotteryTicketMapper.selectTicketsCount(queryReq);
        if (count.longValue() != numberRes.getSubtract().longValue()) {
            throw new BizException("00000001", "序号没有连续，请修改数据序号");
        }

        List<LotteryTicket> list = lotteryTicketMapper.selectTicketList("asc", req.getType(), "fcap_lottery_ticket"+req.getType());
        Map<Long, LotteryTicket> lotteryTicketMap = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            lotteryTicketMap.put(lotteryTicket.getSerialNo(), lotteryTicket);
        }
        Integer big = numberRes.getBig();
        Integer small = numberRes.getSmall();
        long startTime = System.currentTimeMillis();

        LotteryTicket currentObj = lotteryTicketMap.get(req.getSerialNo());
        String[] arr2 = currentObj.getContent().split(",");
        List<String> nextContents = new ArrayList<>();
        for (String aa : arr2) {
            nextContents.add(aa);
        }
        long preId = req.getSerialNo() - 1;
        List<LotteryTicket> tmpList = new ArrayList<>();
        while (preId >= 1) {
            LotteryTicket preObj = lotteryTicketMap.get(preId);
            String[] arr1 = preObj.getContent().split(",");
            List<String> contents = new ArrayList<>();
            for (String bb : arr1) {
                contents.add(bb);
            }
            contents.retainAll(nextContents);
            LotteryTicket tmp = new LotteryTicket();
            tmp.setSerialNo(currentObj.getSerialNo());
            tmp.setOtherSerialNo(preObj.getSerialNo());
            tmp.setType(currentObj.getType());
            if (CollectionUtils.isEmpty(contents)) {
                tmp.setResult(0);
            } else {
                tmp.setResult(1);
            }
            tmpList.add(tmp);

            preId = preId - 1;
        }
        batchInsert(tmpList, req.getType());

        return 1;
    }

    public int updateLotteryTicket(LotteryTicketReq req) {
        req.setTableName("fcap_lottery_ticket"+req.getType());
        lotteryTicketMapper.updateLotteryTicket(req);

        NumberRes numberRes = lotteryTicketMapper.getSubtractSerialNo(req.getType(), "fcap_lottery_ticket"+req.getType());
        if (numberRes == null || numberRes.getBig() == null
                || numberRes.getSmall() == null || numberRes.getSubtract() == null) {
            log.error("jiSuanRepeat numberRes is null, return...");
            return 0;
        }
        if (numberRes.getSubtract().longValue() <= 1) {
            log.error("jiSuanRepeat getSubtract is error, return...");
            return 0;
        }
        List<String> repeatList = lotteryTicketMapper.getRepeatSerialNo(req.getType(), "fcap_lottery_ticket"+req.getType());
        if (!CollectionUtils.isEmpty(repeatList)) {
            throw new BizException("00000001", "这些序号出现了重复" + String.join("，", repeatList) + "。请修改序号");
        }
        LotteryTicketReq queryReq = new LotteryTicketReq();
        queryReq.setType(req.getType());
        queryReq.setTableName("fcap_lottery_ticket"+req.getType());
        Integer count = lotteryTicketMapper.selectTicketsCount(queryReq);
        if (count.longValue() != numberRes.getSubtract().longValue()) {
            throw new BizException("00000001", "序号没有连续，请修改数据序号");
        }

        List<LotteryTicket> list = lotteryTicketMapper.selectTicketList("asc", req.getType(), "fcap_lottery_ticket"+req.getType());
        Map<Long, LotteryTicket> lotteryTicketMap = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            lotteryTicketMap.put(lotteryTicket.getSerialNo(), lotteryTicket);
        }
        Integer big = numberRes.getBig();
        Integer small = numberRes.getSmall();
        long startTime = System.currentTimeMillis();

        LotteryTicket currentObj = lotteryTicketMap.get(req.getSerialNo());
        String[] arr2 = currentObj.getContent().split(",");
        List<String> nextContents = new ArrayList<>();
        for (String aa : arr2) {
            nextContents.add(aa);
        }
        long preId = req.getSerialNo() - 1;
        List<LotteryTicket> tmpList = new ArrayList<>();
        while (preId >= 1) {
            LotteryTicket preObj = lotteryTicketMap.get(preId);
            String[] arr1 = preObj.getContent().split(",");
            List<String> contents = new ArrayList<>();
            for (String bb : arr1) {
                contents.add(bb);
            }
            contents.retainAll(nextContents);
            LotteryTicket tmp = new LotteryTicket();
            tmp.setSerialNo(currentObj.getSerialNo());
            tmp.setOtherSerialNo(preObj.getSerialNo());
            tmp.setType(currentObj.getType());
            if (CollectionUtils.isEmpty(contents)) {
                tmp.setResult(0);
            } else {
                tmp.setResult(1);
            }
            tmpList.add(tmp);

            preId = preId - 1;
        }
        batchInsert(tmpList, req.getType());

        return 1;
    }

    @Transactional
    public int delLotteryTicket(LotteryTicketReq req) {
        req.setTableName("fcap_lottery_ticket"+req.getType());
        req.setTableName2("fcap_lottery_ticket_result"+req.getType());
        int rows = lotteryTicketMapper.delLotteryTicket(req);

        Long id = lotteryTicketMapper.getMaxId(req.getTableName());
        if (id != null) {

            String sql = "alter sequence "+req.getTableName()+"_id_seq restart with " + (id + 1);
            lotteryTicketMapper.restartSequence(sql);
        }else{
            String sql = "alter sequence "+req.getTableName()+"_id_seq restart with " + 1;
            lotteryTicketMapper.restartSequence(sql);
        }

        return rows;
    }

    public void jiSuanRepeat(String calculate, int type) {
        NumberRes numberRes = lotteryTicketMapper.getSubtractSerialNo(type, "fcap_lottery_ticket"+type);
        if (numberRes == null || numberRes.getBig() == null
                || numberRes.getSmall() == null || numberRes.getSubtract() == null) {
            log.error("jiSuanRepeat numberRes is null, return...");
            return;
        }
        if (numberRes.getSubtract().longValue() <= 1) {
            log.error("jiSuanRepeat getSubtract is error, return...");
            return;
        }
        List<String> repeatList = lotteryTicketMapper.getRepeatSerialNo(type, "fcap_lottery_ticket"+type);
        if (!CollectionUtils.isEmpty(repeatList)) {
            throw new BizException("00000001", "这些序号出现了重复" + String.join("，", repeatList) + "。请修改序号");
        }
        LotteryTicketReq queryReq = new LotteryTicketReq();
        queryReq.setType(type);
        queryReq.setTableName("fcap_lottery_ticket"+type);
        Integer count = lotteryTicketMapper.selectTicketsCount(queryReq);
        if (count.longValue() != numberRes.getSubtract().longValue()) {
            throw new BizException("00000001", "序号没有连续，请修改数据序号");
        }

        List<LotteryTicket> list = lotteryTicketMapper.selectTicketList("asc", type, "fcap_lottery_ticket"+type);
        Map<Long, LotteryTicket> map = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            map.put(lotteryTicket.getSerialNo(), lotteryTicket);
        }
        Integer big = numberRes.getBig();
        Integer small = numberRes.getSmall();
        long startTime = System.currentTimeMillis();
        //log.info("======开始计算重复:"+ startTime);
        /*long bigId = big;
        long currentId = small + 1;*/
        if ("1".equals(calculate)) {
            workStealingService.execute(new CalculateRepeatTask(big, big, lotteryTicketMapper, map, type));
        } else {
            for (int i = small + 1; i <= big; i++) {
                workStealingService.execute(new CalculateRepeatTask(i, big, lotteryTicketMapper, map, type));
            }
        }

        //log.info("======计算重复结束 cost:"+ (System.currentTimeMillis() - startTime)/1000 + "秒");
    }

    public void jsRepeat(int type, int small,  int big) {
        NumberRes numberRes = lotteryTicketMapper.getSubtractSerialNo(type, "fcap_lottery_ticket"+type);
        if (numberRes == null || numberRes.getBig() == null
                || numberRes.getSmall() == null || numberRes.getSubtract() == null) {
            log.error("jiSuanRepeat numberRes is null, return...");
            return;
        }
        if (numberRes.getSubtract().longValue() <= 1) {
            log.error("jiSuanRepeat getSubtract is error, return...");
            return;
        }
        List<String> repeatList = lotteryTicketMapper.getRepeatSerialNo(type, "fcap_lottery_ticket"+type);
        if (!CollectionUtils.isEmpty(repeatList)) {
            throw new BizException("00000001", "这些序号出现了重复" + String.join("，", repeatList) + "。请修改序号");
        }
        LotteryTicketReq queryReq = new LotteryTicketReq();
        queryReq.setType(type);
        queryReq.setTableName("fcap_lottery_ticket"+type);
        Integer count = lotteryTicketMapper.selectTicketsCount(queryReq);
        if (count.longValue() != numberRes.getSubtract().longValue()) {
            throw new BizException("00000001", "序号没有连续，请修改数据序号");
        }

        List<LotteryTicket> list = lotteryTicketMapper.selectTicketList("asc", type, "fcap_lottery_ticket"+type);
        Map<Long, LotteryTicket> map = new HashMap<>();
        for (LotteryTicket lotteryTicket : list) {
            map.put(lotteryTicket.getSerialNo(), lotteryTicket);
        }

        for (int i = small; i <= big; i++) {
            workStealingService.execute(new CalculateRepeatTask(i, big, lotteryTicketMapper, map, type));
        }
    }

    private void batchInsert(List<LotteryTicket> tmpList, int type) {
        // 批量插入
        if (!CollectionUtils.isEmpty(tmpList)) {
            List<LotteryTicket> newList = new ArrayList<>();
            for (int i = 0; i < tmpList.size(); i++) {
                newList.add(tmpList.get(i));
                // 每500条数据批量保存一次
                if (i != 0 && i % 500 == 0) {
                    lotteryTicketMapper.batchInsertLotteryTicketResult(tmpList, "fcap_lottery_ticket_result"+type);
                    newList.clear();
                }
            }

            // 最后一个批次数据
            if (newList.size() > 0) {
                lotteryTicketMapper.batchInsertLotteryTicketResult(tmpList, "fcap_lottery_ticket_result"+type);
            }
        }
    }

    static class CalculateRepeatTask implements Runnable {
        private long id; // serialNo
        private long maxId; // serialNo
        private LotteryTicketMapper lotteryTicketMapper;
        private Map<Long, LotteryTicket> lotteryTicketMap;
        private int type;

        public CalculateRepeatTask(long id, long maxId, LotteryTicketMapper lotteryTicketMapper, Map<Long, LotteryTicket> lotteryTicketMap, int type) {
            this.id = id;
            this.lotteryTicketMapper = lotteryTicketMapper;
            this.lotteryTicketMap = lotteryTicketMap;
            this.maxId = maxId;
            this.type= type;
        }

        @Override
        @Transactional
        public void run() {
            LotteryTicket currentObj = lotteryTicketMap.get(id);
            String[] arr2 = currentObj.getContent().split(",");
            List<String> nextContents = new ArrayList<>();
            for (String aa : arr2) {
                nextContents.add(aa);
            }
            long preId = id - 1;
            List<LotteryTicket> tmpList = new ArrayList<>();
            while (preId >= 1) {
                LotteryTicket preObj = lotteryTicketMap.get(preId);
                String[] arr1 = preObj.getContent().split(",");
                List<String> contents = new ArrayList<>();
                for (String bb : arr1) {
                    contents.add(bb);
                }
                contents.retainAll(nextContents);
                LotteryTicket tmp = new LotteryTicket();
                tmp.setSerialNo(currentObj.getSerialNo());
                tmp.setOtherSerialNo(preObj.getSerialNo());
                tmp.setType(currentObj.getType());
                if (CollectionUtils.isEmpty(contents)) {
                    tmp.setResult(0);
                } else {
                    tmp.setResult(1);
                }
                tmpList.add(tmp);

                preId = preId - 1;
            }
            batchInsert(tmpList, type);

/*            if(id == maxId){
                lotteryTicketMapper.deleteLotteryTicketResultTemp();

                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 1);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 2);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 3);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 4);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 5);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 6);
                lotteryTicketMapper.insertLotteryTicketResultTemp(maxId, 7);
            }*/
        }

        private void batchInsert(List<LotteryTicket> tmpList, int type) {
            // 批量插入
            if (!CollectionUtils.isEmpty(tmpList)) {
                List<LotteryTicket> newList = new ArrayList<>();
                for (int i = 0; i < tmpList.size(); i++) {
                    newList.add(tmpList.get(i));
                    // 每500条数据批量保存一次
                    if (i != 0 && i % 500 == 0) {
                        lotteryTicketMapper.batchInsertLotteryTicketResult(tmpList, "fcap_lottery_ticket_result"+type);
                        newList.clear();
                    }
                }

                // 最后一个批次数据
                if (newList.size() > 0) {
                    lotteryTicketMapper.batchInsertLotteryTicketResult(tmpList, "fcap_lottery_ticket_result"+type);
                }
            }
        }

    }


    static class GetWinLotteryTask implements Runnable {
        private int num; //隔几组算重复
        private long maxId; // 序号，最新一期的id
        private int repeat; // 重复次数大于多少，才查出来
        private LotteryTicketMapper lotteryTicketMapper;
        private List<LotteryTicketRes> lotteryTicketList;
        private CountDownLatch countDownLatch;
        private int type;
        public GetWinLotteryTask(int num, long maxId, int repeat,LotteryTicketMapper lotteryTicketMapper, List<LotteryTicketRes> lotteryTicketList, CountDownLatch countDownLatch, int type) {
            this.num = num;
            this.maxId = maxId;
            this.repeat = repeat;
            this.lotteryTicketMapper = lotteryTicketMapper;
            this.lotteryTicketList = lotteryTicketList;
            this.countDownLatch = countDownLatch;
            this.type = type;
        }
        @Override
        public void run() {
            try
            {
                List<LotteryTicketRes> list =  lotteryTicketMapper.selectWinRepeatTicketList(maxId,"fcap_lottery_ticket_result"+type, num, type);
                if(CollectionUtils.isEmpty(list) || list.size()< repeat){
                    //countDownLatch.countDown();
                    return;
                }
                boolean flag = false;
                for(int i = 0; i < list.size(); i++){
                    if(list.get(i).getResult() == 0){
                        flag = true;
                        if((i) >= repeat){
                            long otherSerialNo = list.get(0).getOtherSerialNo();
                            otherSerialNo = otherSerialNo + 1;
                            LotteryTicketRes ticketRes = lotteryTicketMapper.selectTicketByNo(otherSerialNo, type, "fcap_lottery_ticket"+type);
                            ticketRes.setRepeat(Long.valueOf(i));
                            ticketRes.setNum(num);
                            lotteryTicketList.add(ticketRes);
                        }
                        break;
                    }
                }
                if(!flag){
                    if(list.size() >= repeat){
                        long serialNo = list.get(0).getSerialNo();
                        //otherSerialNo = otherSerialNo + 1;
                        LotteryTicketRes ticketRes = lotteryTicketMapper.selectTicketByNo(serialNo, type, "fcap_lottery_ticket"+type);
                        if(ticketRes != null){
                            ticketRes.setRepeat(Long.valueOf(list.size()));
                            ticketRes.setNum(num);
                            lotteryTicketList.add(ticketRes);
                        }
                    }
                }
            }catch (Exception e){
                log.error("exception:", e);
            }finally {
                countDownLatch.countDown();
            }
        }
    }



    @Override
    public List<LotteryTicketRes> getBuyTicketList(LotteryTicketReq req) {
        Integer maxSerialNo = lotteryTicketMapper.getMaxSerialNo(req.getType(), "fcap_lottery_ticket"+req.getType());
        List<LotteryTicketRes> lotteryTicketList = new ArrayList<>();
        if(maxSerialNo == null){
            return new ArrayList<>();
        }
        int num = maxSerialNo-2;
        if(maxSerialNo <= 3){
            return new ArrayList<>();
        }
//        if(req.getType()==3 || req.getType()==4){
//            num = maxSerialNo-2;
//            if(maxSerialNo <= 3){
//                return new ArrayList<>();
//            }
//        }
        CountDownLatch countDownLatch = new CountDownLatch(num);
        for(int i = 1; i <= num; i++){
            workStealingService.execute(new GetWinLotteryTask(i, maxSerialNo , Integer.parseInt(req.getRepeat()+""), lotteryTicketMapper,lotteryTicketList,countDownLatch, req.getType()));
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(!CollectionUtils.isEmpty(lotteryTicketList)){
            lotteryTicketList.sort(new Comparator<LotteryTicketRes>() {
                @Override
                public int compare(LotteryTicketRes o1, LotteryTicketRes o2) {
                    return Integer.parseInt(o2.getRepeat()-o1.getRepeat() + "");
                }
            });
        }

        return lotteryTicketList;
    }
}